/* spi/spi.h
 *
 * SPI interface driver
 *
 * Copyright (c) 2011 by BKIT4U <www.bkit4u.com>
 * Author: BS135 <thanhhai135@gmail.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General  Public  License
 * as published by the Free Software Foundation;version 2 or 2.1
 * of the License. This license can be found at
 *                           http://www.gnu.org/licenses/gpl.txt
 *
 * Target MCU	: Atmel AVR series
 * Editor Tabs	: 4
 */

#ifndef __SPI_H__
#define __SPI_H__

#include <stdint.h>

//! Defines for customisation of sd/mmc port access
#if defined(__AVR_ATmega8__) || \
    defined(__AVR_ATmega48__) || \
    defined(__AVR_ATmega48P__) || \
    defined(__AVR_ATmega88__) || \
    defined(__AVR_ATmega88P__) || \
    defined(__AVR_ATmega168__) || \
    defined(__AVR_ATmega168P__) || \
    defined(__AVR_ATmega328P__)
    #define spi_configure_pin_mosi() 	DDRB |= (1 << DDB3)
    #define spi_configure_pin_sck() 	DDRB |= (1 << DDB5)
    #define spi_configure_pin_ss() 		DDRB |= (1 << DDB2)
    #define spi_configure_pin_miso() 	DDRB &= ~(1 << DDB4)

    #define spi_select_slave() 			PORTB &= ~(1 << PB2)
    #define spi_unselect_slave() 		PORTB |= (1 << PB2)
#elif defined(__AVR_ATmega16__) || \
      defined(__AVR_ATmega32__)
    #define spi_configure_pin_mosi() 	DDRB |= (1 << DDB5)
    #define spi_configure_pin_sck() 	DDRB |= (1 << DDB7)
    #define spi_configure_pin_ss() 		DDRB |= (1 << DDB4)
    #define spi_configure_pin_miso() 	DDRB &= ~(1 << DDB6)

    #define spi_select_slave() 			PORTB &= ~(1 << PB4)
    #define spi_unselect_slave() 		PORTB |= (1 << PB4)
#elif defined(__AVR_ATmega64__) || \
      defined(__AVR_ATmega128__) || \
      defined(__AVR_ATmega169__)
    #define spi_configure_pin_mosi() 	DDRB |= (1 << DDB2)
    #define spi_configure_pin_sck() 	DDRB |= (1 << DDB1)
    #define spi_configure_pin_ss() 		DDRB |= (1 << DDB0)
    #define spi_configure_pin_miso() 	DDRB &= ~(1 << DDB3)

    #define spi_select_slave() 			PORTB &= ~(1 << PB0)
    #define spi_unselect_slave() 		PORTB |= (1 << PB0)
#else
    #error "no sd/mmc pin mapping available!"
#endif

#define spi_configure_pin_select(spi_ddr,spi_ss_pin)	spi_ddr |= (1 << spi_ss_pin)
#define spi_select(spi_port, spi_ss_pin)				spi_port &= ~(1 << spi_ss_pin)
#define spi_unselect(spi_port,spi_ss_pin)				spi_port |= (1 << spi_ss_pin)

//! Initialization SPI I/O pins
void spi_init_hardware();
//! Initialization SPI operation mode at lowest speed
void spi_init_low_mode();
//! Initialization SPI operation mode at fastest speed
void spi_init_fast_mode();
//! Initialization SPI operation mode at custom speed
void spi_init_custom_mode(	uint8_t b_SPIE,
							uint8_t	b_SPE,
							uint8_t b_DORD,
							uint8_t b_MSTR,
							uint8_t b_CPOL,
							uint8_t b_CPHA,
							uint8_t b_SPR1,
							uint8_t b_SPR0,
							uint8_t b_SPI2X);

//! Transfer a byte through spi bus
uint8_t spi_transfer(uint8_t b);

#endif //__SPI_H__
